拿到歌曲資訊後,就可以在畫面顯示啦,要顯示一系列的資訊,最常用的元件就是 RecyclerView 了,還會搭配 Adapter 和 ViewHolder,參考 storage-samples/MediaStore 的 Adapter 寫法是繼承 ListAdapter,然後傳入 DiffUtil.ItemCallback,可以讓 RecyclerView 更有效率更新的元件。
class SongListAdapter(private val onClick: (Song) -> Unit) :
ListAdapter<Song, SongViewHolder>(Song.DiffCallback)
關於在 Song 的 DiffCallback,直接用 Song 的 Id 判斷是否為同一首:
val DiffCallback = object : DiffUtil.ItemCallback<Song>() {
override fun areItemsTheSame(oldItem: Song, newItem: Song) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Song, newItem: Song) =
oldItem == newItem
}
在 SongListAdapter 內的 onBindViewHolder:
override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
val mediaStoreSong = getItem(position)
holder.itemView.songLayout.tag = mediaStoreSong
holder.itemView.songNameText.text = mediaStoreSong.title
holder.itemView.artistNameText.text = mediaStoreSong.artistName
Glide.with(holder.itemView.context)
.load(mediaStoreSong.coverPath)
.centerCrop()
.into(holder.itemView.songCoverImage)
}
有三個 UI 元件,分別是顯示歌名、歌手名稱、專輯封面,顯示圖片使用 Glide 來顯示圖片。
在 ViewHolder :
class SongViewHolder(private val view: View, onClick: (Song) -> Unit) :
RecyclerView.ViewHolder(view), LayoutContainer {
override val containerView: View?
get() = view
init {
view.songLayout.setOnClickListener {
val song = view.songLayout.tag as? Song ?: return@setOnClickListener
onClick(song)
}
}
}
ViewHolder 的部分,就比較一般,傳入點擊的 lamda 參數,使用者點擊歌曲時,可以回傳點擊的歌曲物件,並使用 Kotlin extension 綁定 view id。
關於 UI 排版有一個地方要稍微注意一下的地方是,歌曲和歌手名稱長度可能會很長,需要限制行數,並且讓顯示不完的字數在後面顯示 ...
<item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item>
使用端的程式,初始化 SongListAdapter 和 songRecyclerView,並使用 LiveData 的方式來觀察是否有歌曲,有歌曲就通知 songAdapter:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val songAdapter = SongListAdapter {
clickSong(it)
}
with(songRecyclerView) {
layoutManager = LinearLayoutManager(activity)
adapter = songAdapter
}
songListViewModel.songs.observe(this.viewLifecycleOwner, Observer<List<Song>> { songs -> songAdapter.submitList(songs)
})
}
程式碼在這,分支名稱(day6_show_songs):Fancy/day6_show_songs
到這邊,歌曲列表顯示就大功告成啦!明天就要來播這些歌了嗎?先等一下,還有一件事要處理 XD